package user

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-oauth2/oauth2/v4"
	"github.com/go-oauth2/oauth2/v4/manage"
	oauthModels "github.com/go-oauth2/oauth2/v4/models"
	"github.com/go-oauth2/oauth2/v4/store"
	"lib/mall/v1/controller"
	"lib/mall/v1/controller/user/forms"
	"lib/mall/v1/helpers"
	"lib/mall/v1/lib"
	"lib/mall/v1/models/userModels"
	"lib/mall/v1/plugins"
	"strconv"
	"time"
)

type Auth struct {
	controller.Controller
}

var instance *Auth

func init() {
	instance = &Auth{}
}

func NewAuthController() *Auth {
	return instance
}

// Login 用户登录
func (this *Auth) Login(ctx *lib.Context) {
	var data forms.AuthLoginForms
	ctx.MustValidate(&data)
	var user userModels.User
	res := ctx.Db.Where("phone=? and password=?", data.Username, helpers.PasswordEncrypt(data.Password)).First(&user)
	if res.RowsAffected == 0 {
		ctx.ThrowError("用户名或者密码错误")
	}
	manager := plugins.NewOAuthManager()
	tgr := &oauth2.TokenGenerateRequest{
		ClientID:     "aaa",
		ClientSecret: "123",
		UserID:       strconv.Itoa(int(user.ID)),
		Scope:        "all",
		Request:      ctx.Request,
	}
	tokenInfo, err := manager.GenerateAccessToken(ctx, oauth2.ClientCredentials, tgr)
	if err != nil { // invalid_client
		ctx.ThrowError("登录密钥生成失败")
	}
	tokenData := gin.H{
		"Access":           tokenInfo.GetAccess(),
		"AccessCreateAt":   tokenInfo.GetAccessCreateAt().Format("2006-01-02 15:04:05"),
		"AccessExpiresIn":  tokenInfo.GetAccessExpiresIn() / time.Millisecond,
		"Refresh":          tokenInfo.GetRefresh(),
		"RefreshCreateAt":  tokenInfo.GetRefreshCreateAt().Format("2006-01-02 15:04:05"),
		"RefreshExpiresIn": tokenInfo.GetRefreshExpiresIn() / time.Millisecond,
	}

	ctx.Success(gin.H{
		"token":    tokenData,
		"userInfo": user,
	}, "登录成功")
}

func (this *Auth) Refresh(ctx *lib.Context) {

}

func (this *Auth) Logout(ctx *lib.Context) {

}

func (this *Auth) Token(ctx *lib.Context) {
	manager := manage.NewDefaultManager()
	manager.SetClientTokenCfg(manage.DefaultPasswordTokenCfg)
	manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg)
	// token memory store
	manager.MustTokenStorage(store.NewMemoryTokenStore())

	// client memory store
	clientStore := store.NewClientStore()
	clientStore.Set("a", &oauthModels.Client{
		ID:     "name",
		Secret: "999999",
		Domain: "http://localhost",
	})
	manager.MapClientStorage(clientStore)

	tgr := &oauth2.TokenGenerateRequest{
		ClientID:     "a",
		ClientSecret: "999999",
		UserID:       "user_id_ini",
		Scope:        "all",
		Request:      ctx.Request,
	}
	tokenInfo, err := manager.GenerateAccessToken(ctx, oauth2.ClientCredentials, tgr)
	if err != nil {
		fmt.Printf("errT:%T,errV:%v \n", err, err.Error())
		return
	}
	fmt.Printf("reToken:%v ExpiresIn:%v \n", tokenInfo.GetRefresh(), tokenInfo.GetAccessExpiresIn())
	info, _ := manager.GetClient(ctx, "a")

	tokenData, err := manager.LoadAccessToken(ctx, tokenInfo.GetAccess())
	if err != nil {
		fmt.Printf("tokenData errT:%T,errV:%V \n", err, err)
		return
	}

	refreshData, err := manager.LoadRefreshToken(ctx, tokenInfo.GetRefresh())
	if err != nil {
		fmt.Printf("refreshData errT:%T,errV:%V \n", err, err)
		return
	}
	ctx.Success(gin.H{
		"token":       tokenInfo,
		"client":      info,
		"tokenData":   tokenData,
		"refreshData": refreshData,
	}, "ok")
}
